package com.ease.component.controls.tree {

import flash.events.MouseEvent;

import mx.controls.CheckBox;
import mx.core.mx_internal;

use namespace mx_internal;

[Style(name = "transientUpIcon", type = "Class", inherit = "no")]

[Style(name = "transientOverIcon", type = "Class", inherit = "no")]

[Style(name = "transientDownIcon", type = "Class", inherit = "no")]

[Style(name = "transientDisabledIcon", type = "Class", inherit = "no")]

public class TriStateCheckBox extends CheckBox {

   //---------------------------------------------------------------------------
   // Class Constants

   /**
    * Constant to represent the <code>unchecked</code> state of this tri state
    * check box.
    *
    * @see #state
    */
   public static const STATE_UNCHECKED:String = "unchecked";

   /**
    * Constant to represent the <code>transient</code> state of this tri state
    * check box.
    *
    * @see #state
    */
   public static const STATE_TRANSIENT:String = "transient";

   /**
    * Constant to represent the <code>checked</code> state of this tri state
    * check box.
    *
    * @see #state
    */
   public static const STATE_CHECKED:String = "checked";

   //---------------------------------------------------------------------------
   // Constructor

   /**
    * Creates a tri state check box with a default state (unchecked) and
    * disableTriStatesForUserActions (false).
    */
   public function TriStateCheckBox() {
      super();

      this.state = STATE_UNCHECKED;
      this.disableTriStatesForUserActions = false;
   }

   //---------------------------------------------------------------------------
   // Instance Variables

   /**
    * Property for optimally updating changes in the <code>state</code> of this
    * tri state check box.
    */
   private var _stateChanged:Boolean;

   //---------------------------------------------------------------------------
   // Overridden Properties

   /**
    * @inheritDoc
    */
   override public function set selected(value:Boolean):void {
      super.selected = value;
      synchState();
   }

   //---------------------------------------------------------------------------
   // Instance Properties

   //-------------------------------------------------------
   // state

   private var _state:String;

   [Inspectable(type = "String", enumeration = "unchecked,transient,checked", defaultValue = "unchecked")]

   [Bindable]

   /**
    * Represents the state of this tri state check box control. The possible
    * values for the state are <code>unchecked</code>, <code>transient</code> and
    * <code>checked</code>.
    */
   public function get state():String {
      return _state;
   }

   /** @private */
   public function set state(value:String):void {
      if (value == _state || (value != STATE_UNCHECKED
            && value != STATE_TRANSIENT && value != STATE_CHECKED)) {
         return;
      }

      _state = value;
      _stateChanged = true;
      invalidateProperties();
   }

   //-------------------------------------------------------
   // disableTriStatesForUserActions

   private var _disableTriStatesForUserActions:Boolean;

   [Inspectable(type = "Boolean", enumeration = "true,false", defaultValue = "false")]

   /**
    * Disables this tri state check box's <code>transient</code> state selection
    * form the mouse and keyboard events. However the <code>transient</code> state
    * can be selected programmatically using the <code>state</code> property.
    *
    * @default false
    */
   public function get disableTriStatesForUserActions():Boolean {
      return _disableTriStatesForUserActions;
   }

   /** @private */
   public function set disableTriStatesForUserActions(value:Boolean):void {
      if (value == _disableTriStatesForUserActions) {
         return;
      }

      _disableTriStatesForUserActions = value;
   }

   //---------------------------------------------------------------------------
   // Overridden Methods

   /**
    * @inheritDoc
    */
   override protected function commitProperties():void {
      super.commitProperties();

      if (_stateChanged) {
         var isSelected:Boolean = (_state == STATE_CHECKED);
         this.setSelected(isSelected, true);
         invalidateDisplayList();
         _stateChanged = false;
      }
   }

   /**
    * @inheritDoc
    */
   override mx_internal function getCurrentIconName():String {
      var iconName:String = super.getCurrentIconName();

      if (_state == STATE_TRANSIENT) {
         if (!this.enabled) {
            iconName = "transientDisabledIcon"
         } else if (this.phase == "up") {
            iconName = "transientUpIcon";
         } else if (this.phase == "over") {
            iconName = "transientOverIcon";
         } else if (this.phase == "down") {
            iconName = "transientDownIcon";
         }
      }

      return iconName;
   }

   /**
    * @inheritDoc
    */
   override protected function clickHandler(event:MouseEvent):void {
      if (!this.enabled) {
         event.stopImmediatePropagation();
         return;
      }

      if (_disableTriStatesForUserActions) {
         this.selected = !this.selected;
      } else {
         var isSelected:Boolean;

         if (_state == STATE_TRANSIENT) {
            isSelected = true;
            state = STATE_CHECKED;
         } else if (this.selected) {
            state = STATE_UNCHECKED;
         } else {
            state = STATE_TRANSIENT;
         }

         this.setSelected(isSelected, true);
      }

      event.updateAfterEvent();
   }

   //---------------------------------------------------------------------------
   // Instance Methods

   /**
    * Syncs the state of this tri state check box to the selected property.
    */
   private function synchState():void {
      state = (this.selected) ? STATE_CHECKED : STATE_UNCHECKED;
   }
}
}